package com.yl.message.websocket

import com.alibaba.fastjson.JSONObject
import com.yl.common.ErrorCode
import com.yl.common.control.ResponseBody
import com.yl.common.control.returnError
import com.yl.common.control.returnSuccess
import com.yl.common.getContext
import com.yl.common.setContext
import com.yl.common.utils.checkTokenAndGetValue
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import java.io.IOException
import java.util.concurrent.ConcurrentHashMap
import javax.websocket.*
import javax.websocket.server.PathParam
import javax.websocket.server.ServerEndpoint

@ServerEndpoint("/webscoket/server/{token}")
@Component
open class WebSocketServer {

	companion object {
		private val log = LoggerFactory.getLogger(WebSocketServer::class.java)!!

		/** 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。  */
		private var onlineCount = 0

		/** concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。  */
		private val webSocketMap: ConcurrentHashMap<String, MutableList<WebSocketServer>> =
			ConcurrentHashMap<String, MutableList<WebSocketServer>>()

		/**
		 * 发送自定义消息
		 */
		@Throws(IOException::class)
		fun sendInfo(userId: String,  message: JSONObject): ResponseBody {
			log.info("发送消息到:$userId，报文:$message")
			return if (webSocketMap.containsKey(userId)) {
				for(socket in webSocketMap[userId]!!){
					socket.sendMessage(message.toString())
				}
				returnSuccess()
			} else {
				log.error("用户$userId,不在线！")
				returnError(ErrorCode.SEND_MESSAGE_ERROR,"用户$userId,不在线！")
			}
		}
	}



	/** 与某个客户端的连接会话，需要通过它来给客户端发送数据  */
	private lateinit var session: Session

	/** 接收userId  */
	private var userId = ""

	// 在线用户列表
	private val users: MutableMap<String, Session> = mutableMapOf()

	private  val token_key: String = "ylqqwdytjh"


	/**
	 * 连接建立成功调用的方法
	 */
	@OnOpen
	open fun onOpen( session: Session,@PathParam("token")token:String) {
		log.info("成功建立websocket连接;{}", getContext())
		try {
			setContext(checkTokenAndGetValue(token, token_key))
		} catch (e: Exception) {
			log.error("检验token出现异常:{}", e.message)
			this.sendMessage(JSONObject.toJSONString(WebSocketMessageVo(WebSocketMessageType.TEXT, "token异常")))
			return
		}
		this.session = session

		userId = getContext().userId.toString()

		if (!webSocketMap.containsKey(userId)) {
			webSocketMap[userId] = mutableListOf()
		}
		webSocketMap[userId]!!.add(this)
		this.sendMessage(JSONObject.toJSONString(WebSocketMessageVo(WebSocketMessageType.TEXT, "连接成功")))
	}

	/**
	 * 收到客户端消息后调用的方法
	 *
	 * @param message
	 * 客户端发送过来的消息
	 */
	@OnMessage
	open fun onMessage(message: String, session: Session) {
		log.info("收到客户端消息：{}", message)
		val msgJson = JSONObject.parseObject(message)

	}

	/**
	 * 连接关闭调用的方法
	 */
	@OnClose
	open fun onClose() {
		if(webSocketMap[userId] != null){
			webSocketMap[userId]!!.remove(this)
		}
		if(webSocketMap[userId]!!.size == 0){
			webSocketMap.remove(userId)
			users.remove(userId)
		}
	}


	@OnError
	open fun onError(session: Session, error: Throwable) {
		log.error("用户错误:" + userId + ",原因:" + error.message)
		if(webSocketMap[userId] != null){
			webSocketMap[userId]!!.remove(this)
		}
		if(webSocketMap[userId]!!.size == 0){
			webSocketMap.remove(userId)
			users.remove(userId)
		}
		error.printStackTrace()
	}


	/**
	 * 实现服务器主动推送
	 */
	@Throws(IOException::class)
	open fun sendMessage(message: String?) {
		try{
			session.basicRemote.sendText(message)
		}catch (e:Exception){
			e.printStackTrace()
		}
	}

	@Synchronized
	open fun getOnlineCount(): Int {
		return onlineCount
	}

	@Synchronized
	open fun addOnlineCount() {
		onlineCount++
	}

	@Synchronized
	open fun subOnlineCount() {
		onlineCount--
	}


}
